#include "PrecompiledHeader.h"
#include "CResources.h"

/*--------------------------------------------------------------------------*/
CResources* g_Resources = NULL;
/*--------------------------------------------------------------------------*/

CResources::CResources() :
	IEngMod("CResources")
{
	AssertModule(g_Shell);
	g_Shell->RegisterLuaFunction("reloadshaders", sh::reloadshaders);
}

/*--------------------------------------------------------------------------*/

CResources::~CResources()
{
	uint size = this->m_resourceGeneratorsVec.size();

	for (uint i = 0; i < size; ++i)
	{
		delete this->m_resourceGeneratorsVec[i];
	}
}

/*--------------------------------------------------------------------------*/

void CResources::LoadResources(const std::string& file)
{
	pugi::xml_document rfile;
	AssertLogC(rfile.load_file(file.c_str()) == false, "File %s not found!", file.c_str());

	Timer timer;
	pugi::xml_node resources = rfile.child("resources");
	std::vector<IResource*> loadedResources;

	{
		/*--------------------------------------------------------------------------*/
		timer.SetTimer();

		for (pugi::xml_node r = resources.child("font"); r; r = r.next_sibling("font"))
		{
			std::string name = r.attribute("name").as_string();
			std::string file = r.attribute("file").as_string();
			float size = r.attribute("size").as_float();

			Font* font = new Font(file, size);

			this->Add(name, font);
			loadedResources.push_back(font);
		}

		AssertLogI(true, "Fonts created in %f ms.", timer.GetTimer());
	}

	{
		/*--------------------------------------------------------------------------*/
		timer.SetTimer();

		for (pugi::xml_node r = resources.child("texture"); r; r = r.next_sibling("texture"))
		{
			std::string name = r.attribute("name").as_string();
			std::string file = r.attribute("file").as_string();

			TextureRes* textureRes = new TextureRes(name, file);

			this->Add(name, textureRes);
			loadedResources.push_back(textureRes);
		}

		AssertLogI(true, "Textures created in %f ms.", timer.GetTimer());
	}

	AssertModule(g_Shell);

// 	{
// 		/*--------------------------------------------------------------------------*/
// 		timer.SetTimer();
//
// 		for (pugi::xml_node r = resources.child("shader"); r; r = r.next_sibling("shader"))
// 		{
// 			std::string name = r.attribute("name").as_string();
// 			std::string file = r.attribute("file").as_string();
//
// 			this->Add(name, new ShaderRes(file));
// 		}
//
// 		AssertLogI(true, "Shaders created in %f ms.", timer.GetTimer());
// 	}

	{
		/*--------------------------------------------------------------------------*/
		timer.SetTimer();

		for (pugi::xml_node r = resources.child("gui"); r; r = r.next_sibling("gui"))
		{
			std::string name = r.attribute("name").as_string();
			std::string file = r.attribute("file").as_string();

			Gui* gui = new Gui(file);

			this->Add(name, gui);
			loadedResources.push_back(gui);
		}

		AssertLogI(true, "GUIs created in %f ms.", timer.GetTimer());
	}

	{
		/*--------------------------------------------------------------------------*/
		timer.SetTimer();

		for (pugi::xml_node r = resources.child("sound"); r; r = r.next_sibling("sound"))
		{
			std::string name = r.attribute("name").as_string();
			std::string file = r.attribute("file").as_string();

			Sound* sound = new Sound(file);

			this->Add(name, sound);
			loadedResources.push_back(sound);
		}

		AssertLogI(true, "Sounds created in %f ms.", timer.GetTimer());
	}

	{
		/*--------------------------------------------------------------------------*/
		timer.SetTimer();

		for (pugi::xml_node r = resources.child("music"); r; r = r.next_sibling("music"))
		{
			std::string name = r.attribute("name").as_string();
			std::string file = r.attribute("file").as_string();

			Music* music = new Music(file);

			this->Add(name, music);
			loadedResources.push_back(music);
		}

		AssertLogI(true, "Musics created in %f ms.", timer.GetTimer());
	}

	{
		/*--------------------------------------------------------------------------*/
		timer.SetTimer();

		for (pugi::xml_node r = resources.child("mesh"); r; r = r.next_sibling("mesh"))
		{
			std::string name = r.attribute("name").as_string();
			std::string file = r.attribute("file").as_string();

			Mesh* mesh = new Mesh(file);

			this->Add(name, mesh);
			loadedResources.push_back(mesh);
		}

		AssertLogI(true, "Meshes created in %f ms.", timer.GetTimer());

	}

	g_Resources->Reload(loadedResources);
}

/*--------------------------------------------------------------------------*/

void CResources::ReloadShaders()
{
// 	uint size = this->m_resourceGeneratorsVec.size();
// 	ResourceGenerator<Shader>* ptn = NULL;
//
// 	for (uint i = 0; i < size; ++i)
// 	{
// 		ptn = dynamic_cast<ResourceGenerator<Shader>*>(this->m_resourceGeneratorsVec[i]);
//
// 		if (ptn)
// 		{
// 			break;
// 		}
// 	}
//
// 	if (ptn != NULL)
// 	{
// 		for (std::map<std::string, Shader*>::const_iterator iter = ptn->GetItems().begin(); iter != ptn->GetItems().end(); ++ iter)
// 		{
// 			iter->second->Reload();
// 		}
// 	}
}

/*--------------------------------------------------------------------------*/

void CResources::ReloadAll()
{
	AssertLogI(true, "Reloading all resources");

	Timer t;
	uint size = this->m_resourceGeneratorsVec.size();

	for (uint i = 0; i < size; ++i)
	{
		t.SetTimer();

		this->m_resourceGeneratorsVec[i]->ReloadAll();

		AssertLogI(true, "Reloading %s took %f ms.", this->m_resourceGeneratorsVec[i]->GetTypeName().c_str(), t.GetTimer());
	}
}

/*--------------------------------------------------------------------------*/

void CResources::Reload(std::vector<IResource*>& resources)
{
	for (auto iter = resources.begin(); iter != resources.end(); ++iter)
	{
		(*iter)->Reload();
	}
}

/*--------------------------------------------------------------------------*/

void sh::reloadshaders()
{
	AssertModule(g_Resources);
	g_Resources->ReloadShaders();
}

/*--------------------------------------------------------------------------*/